<template>
  <div class="data-analysis" ref="vantaRef">
    <el-card class="main-card">
      <div slot="header">
        <h2>数据分析系统</h2>
      </div>
      <!-- 步骤导航 -->
      <el-steps :active="currentStep" finish-status="success" align-center>
        <el-step title="数据上传" icon="el-icon-upload"></el-step>
        <el-step title="数据清洗" icon="el-icon-edit"></el-step>
        <el-step title="数据分析" icon="el-icon-s-data"></el-step>
        <el-step title="数据可视化" icon="el-icon-pie-chart"></el-step>
        <el-step title="导出结果" icon="el-icon-download"></el-step>
      </el-steps>
      <!-- 步骤内容区域 -->
      <div class="step-content">
        <!-- 步骤1：数据上传 -->
        <div v-show="currentStep === 0">
          <h3>数据上传</h3>
          <div class="upload-preview-row">
            <!-- 左侧上传区域 -->
            <div class="upload-area-centered">
              <div class="upload-form-vertical">
                <el-input 
                  v-model="fileDescription" 
                  type="textarea" 
                  :rows="2" 
                  placeholder="请输入数据集描述信息（可选）">
                </el-input>
                <div class="custom-upload-area" 
                     @dragover.prevent 
                     @drop.prevent="handleFileDrop">
                  <input 
                    type="file" 
                    ref="fileInput" 
                    @change="handleFileSelect" 
                    accept=".csv,.xlsx,.xls" 
                    style="display: none">
                  <div class="upload-icon">
                    <i class="el-icon-upload"></i>
                  </div>
                  <div class="upload-text">
                    将文件拖到此处，或<span class="upload-link" @click="triggerFileInput">点击上传</span>
                  </div>
                  <div class="upload-tip">支持上传CSV/Excel文件</div>
                </div>
                
                <!-- 已选择文件列表 -->
                <div v-if="selectedFile" class="selected-file">
                  <div class="file-info">
                    <i class="el-icon-document"></i>
                    <span class="file-name">{{ selectedFile.name }}</span>
                    <span class="file-size">({{ formatFileSize(selectedFile.size) }})</span>
                  </div>
                  <i class="el-icon-delete" @click="removeFile"></i>
                </div>
                <div class="upload-btn-center">
                  <el-button 
                    type="primary" 
                    style="margin-top: 20px;" 
                    @click="uploadFile" 
                    :disabled="!selectedFile">
                    开始上传
                  </el-button>
                </div>
                <el-progress 
                  v-if="uploadProgress > 0 && uploadProgress < 100" 
                  :percentage="uploadProgress" 
                  :stroke-width="15">
                </el-progress>
              </div>
            </div>
            <!-- 右侧文件预览区域 -->
            <div class="file-preview-area" style="overflow: auto;">
              <h4>文件预览（前5行）</h4>
              <el-table :data="tableData.slice(0, 5)" border style="width: 100%">
                <el-table-column 
                  v-for="(col, index) in tableColumns" 
                  :key="index" 
                  :prop="col" 
                  :label="col">
                </el-table-column>
              </el-table>
            </div>
          </div>
        </div>
        
        <!-- 步骤2：数据清洗 -->
        <div v-show="currentStep === 1">
          <h3>数据清洗</h3>
          <el-form label-width="120px" class="cleaning-form">
            <el-form-item label="缺失值处理">
              <el-radio-group v-model="cleaningOptions.missingValues">
                <el-radio label="mean">使用均值填充</el-radio>
                <el-radio label="median">使用中位数填充</el-radio>
                <el-radio label="mode">使用众数填充</el-radio>
              </el-radio-group>
            </el-form-item>
          
            <el-form-item label="异常值检测">
              <el-switch v-model="cleaningOptions.detectOutliers"></el-switch>
              <span class="option-desc">启用后将检测并处理异常值</span>
            </el-form-item>

            <el-button type="primary" @click="cleanData">执行清洗</el-button>
          </el-form>
          
        </div>
        
        <!-- 步骤3：数据分析 -->
        <div v-show="currentStep === 2">
          <h3>数据分析</h3>
          <el-form label-width="120px" class="analysis-form">
            <el-form-item label="分析方法">
              <el-select v-model="analysisOptions.method" placeholder="请选择分析方法">
                <el-option label="聚类分析 (K-Means)" value="kmeans"></el-option>
                <el-option label="回归分析 (线性回归)" value="linear_regression"></el-option>
              </el-select>
            </el-form-item>
            
            <!-- 添加聚类数量选择器，仅在选择K-Means时显示 -->
            <el-form-item label="聚类数量" v-if="analysisOptions.method === 'kmeans'">
              <el-slider
                v-model="analysisOptions.clusters"
                :min="2"
                :max="5"
                :step="1"
                show-stops
                show-input
                :marks="{2: '2', 5: '5'}"
              ></el-slider>
            </el-form-item>
             
            <el-button type="primary" @click="analyzeData">执行分析</el-button>
          </el-form>
          
          <!-- 分析结果 -->
          <div v-if="analysisResults" class="analysis-results">
            <h4>分析结果</h4>
            <el-card class="result-card">
              <pre>{{ analysisResults }}</pre>
            </el-card>
          </div>
        </div>
        
        <!-- 步骤4：数据可视化 -->
        <div v-show="currentStep === 3">
          <h3>数据可视化</h3>
          <el-form label-width="120px" class="visualization-form">
            <el-form-item label="图表类型">
              <el-select v-model="visualizationOptions.chartType" placeholder="请选择图表类型">
                <!-- 聚类分析(K-means)的图表选项 -->
                <template v-if="analysisOptions.method === 'kmeans'">
                  <el-option label="轮廓图" value="bar"></el-option>
                  <el-option label="散点图" value="scatter"></el-option>
                  <el-option label="热力图" value="heatmap"></el-option>
                  <el-option label="雷达图" value="radar"></el-option>
                </template>
                
                <!-- 回归分析(线性回归)的图表选项 -->
                <template v-else-if="analysisOptions.method === 'linear_regression'">
                  <el-option label="散点图" value="scatter"></el-option>
                  <el-option label="残差图" value="line"></el-option>
                </template>
                
                <!-- 默认图表选项，当没有选择分析方法时显示 -->
                <template v-else>
                  <el-option label="柱状图" value="bar"></el-option>
                  <el-option label="折线图" value="line"></el-option>
                  <el-option label="饼图" value="pie"></el-option>
                  <el-option label="散点图" value="scatter"></el-option>
                  <el-option label="热力图" value="heatmap"></el-option>
                  <el-option label="雷达图" value="radar"></el-option>
                </template>
              </el-select>
            </el-form-item>

            <el-button type="primary" @click="generateChart">生成图表</el-button>
          </el-form>
          
          <!-- 图表展示区域 -->
          <div id="chartContainer" style="width: 100%; height: 400px;"></div>
        </div>
        
        <!-- 步骤5：导出结果 -->
        <div v-show="currentStep === 4">
          <h3>导出结果</h3>
          <el-card class="export-card">
            <div class="export-options">
              
              <h4>导出格式</h4>
              <el-radio-group v-model="exportOptions.format">
                <el-radio label="csv">CSV</el-radio>
                <el-radio label="excel">Excel</el-radio>
              </el-radio-group>
              
              <el-button type="success" style="margin-top: 20px" @click="exportData">导出数据</el-button>
            </div>
          </el-card>
        </div>
      </div>
      
      <!-- 步骤控制按钮 -->
      <!-- 步骤控制按钮 -->
      <div class="step-controls">
        <el-button v-if="currentStep > 0" @click="prevStep">上一步</el-button>
        <el-button v-if="currentStep < 4 " type="primary" @click="nextStep">下一步</el-button>
      </div>
    </el-card>
  </div>
</template>

<script>
import * as XLSX from 'xlsx';
export default {
  name: 'DataAnalysis',
  data() {
    return {
      vantaEffect: null,
      currentStep: 0,
      fileList: [],
      selectedFile: null,
      uploadProgress: 0,
      tableData: [],
      tableColumns: [],
      cleanedData: [],
      datasetId: null, // 添加数据集ID属性
      uploadUrl: 'http://10.76.213.64:5000/api/data/upload',  // 改为相对路径
      fileDescription: '',
      uploadData: {}, // 用于存储上传时的额外参数
      cleaningOptions: {
        missingValues: 'mean',
        detectOutliers: true,  // 修改为 true，使按钮默认选中
        normalize: false
      },
      analysisOptions: {
        method: 'kmeans',
        targetVariable: '',
        features: [],
        clusters: 3,  // 添加聚类数量属性
        taskId: null  // 添加任务ID属性，用于后续可视化
      },
      analysisResults: null,
      visualizationOptions: {
        chartType: 'bar',
        xAxis: '',
        yAxis: '',
        category: '',
        value: ''
      },
      exportOptions: {
        content: ['cleanedData'],
        format: 'csv'
      },
      chart: null
    }
  },
  watch: {
    // 监听文件描述变化，更新上传参数
    fileDescription(val) {
      if (val) {
        this.uploadData.description = val;
      } else {
        delete this.uploadData.description;
      }
    }
  },
  methods: {
    // 触发文件选择框
    triggerFileInput() {
      this.$refs.fileInput.click();
    },
    
    // 处理文件选择
    handleFileSelect(event) {
      const file = event.target.files[0];
      if (file) {
        this.validateAndSetFile(file);
      }
    },
    
    // 处理文件拖放
    handleFileDrop(event) {
      const file = event.dataTransfer.files[0];
      if (file) {
        this.validateAndSetFile(file);
      }
    },
    
    // 验证并设置文件
    validateAndSetFile(file) {
      const isCSV = file.name.endsWith('.csv');
      const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
      
      if (!isCSV && !isExcel) {
        this.$message.error('只能上传CSV或Excel文件!');
        return;
      }
      
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        this.$message.error('文件大小不能超过10MB!');
        return;
      }
      
      this.selectedFile = file;
      this.uploadProgress = 0;
      
      // 前端解析文件并预览
      const reader = new FileReader();
      reader.onload = (e) => {
        try {
          let data, workbook, worksheet, jsonData;
          
          if (isExcel) {
            // 处理Excel文件
            data = new Uint8Array(e.target.result);
            workbook = XLSX.read(data, { type: 'array' });
            const firstSheetName = workbook.SheetNames[0];
            worksheet = workbook.Sheets[firstSheetName];
          } else if (isCSV) {
            // 处理CSV文件
            const csvText = e.target.result;
            workbook = XLSX.read(csvText, { type: 'string' });
            const firstSheetName = workbook.SheetNames[0];
            worksheet = workbook.Sheets[firstSheetName];
          }
          
          // 将工作表转换为JSON数据
          jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
          
          if (jsonData && jsonData.length > 0) {
            // 提取表头和数据
            this.tableColumns = jsonData[0];
            
            // 将数据转换为对象数组格式，以便在el-table中显示
            this.tableData = jsonData.slice(1).map(row => {
              const obj = {};
              this.tableColumns.forEach((col, idx) => {
                obj[col] = row[idx];
              });
              return obj;
            });
            
            this.$message.success('文件预览成功');
          } else {
            this.tableColumns = [];
            this.tableData = [];
            this.$message.warning('文件内容为空');
          }
        } catch (error) {
          console.error('文件解析错误:', error);
          this.$message.error('文件解析失败: ' + error.message);
          this.tableColumns = [];
          this.tableData = [];
        }
      };
      
      reader.onerror = () => {
        this.$message.error('文件读取失败');
      };
      
      // 根据文件类型选择不同的读取方式
      if (isExcel) {
        reader.readAsArrayBuffer(file);
      } else if (isCSV) {
        reader.readAsText(file, 'utf-8');
      }
    },
    
    // 移除已选择的文件
    removeFile() {
      this.selectedFile = null;
      this.uploadProgress = 0;
      // 重置文件输入框，允许重新选择同一文件
      this.$refs.fileInput.value = '';
    },
    
    // 格式化文件大小
    formatFileSize(size) {
      if (size < 1024) {
        return size + ' B';
      } else if (size < 1024 * 1024) {
        return (size / 1024).toFixed(2) + ' KB';
      } else {
        return (size / (1024 * 1024)).toFixed(2) + ' MB';
      }
    },
    
    // 上传文件
    uploadFile() {
      if (!this.selectedFile) {
        this.$message.warning('请先选择文件');
        return;
      }
      
      const formData = new FormData();
      formData.append('file', this.selectedFile);
      
      // 添加描述（如果有）
      if (this.fileDescription) {
        formData.append('description', this.fileDescription);
      }
      
      this.$message.info('正在上传文件...');
      this.uploadProgress = 1; // 开始上传
      
      // 使用axios上传文件
      this.$axios.post(this.uploadUrl, formData, {
        headers: {
          // 不要手动设置 Content-Type，让浏览器自动处理
        },
        onUploadProgress: progressEvent => {
          // 计算上传进度
          const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
          this.uploadProgress = percentCompleted;
        }
      })
      .then(response => {
        this.$message.success('文件上传成功');
        console.log('上传成功响应:', response);
        
        // 处理返回的数据
        if (response.data && response.data.data) {
          this.tableData = response.data.data.rows || [];
          this.tableColumns = response.data.data.columns || [];
          // 保存数据集ID
          if (response.data.data.id) {
            this.datasetId = response.data.data.id;
            console.log('获取到数据集ID:', this.datasetId);
            // 可以在这里显示数据集ID给用户
            this.$message.info(`数据集ID: ${this.datasetId}`);
          } else {
            console.warn('服务器返回的数据中没有包含数据集ID');
            this.$message.warning('未能获取数据集ID，可能影响后续操作');
          }
          // 上传成功后自动进入下一步
          this.nextStep();
        }
      })
      .catch(error => {
        this.uploadProgress = 0;
        console.error('上传失败详情:', error);
        
        let errorMessage = '文件上传失败';
        if (error.response) {
          console.error('错误状态码:', error.response.status);
          console.error('错误响应数据:', error.response.data);
          errorMessage += `: 服务器返回错误代码 ${error.response.status}`;
        } else if (error.request) {
          console.error('请求未收到响应:', error.request);
          errorMessage += ': 服务器未响应请求';
        } else if (error.message) {
          errorMessage += `: ${error.message}`;
        }
        
        this.$message.error(errorMessage);
      });
    },
    
    cleanData() {
      // 检查是否有数据集ID
      if (!this.datasetId) {
        this.$message.error('缺少数据集ID，请先上传数据');
        return;
      }
      
      // 准备请求参数，只包含必要的dataset_id和method
      const params = {
        dataset_id: this.datasetId,
        method: this.cleaningOptions.missingValues
      };
      
      // 如果启用了异常值检测，可以添加这个参数
      if (this.cleaningOptions.detectOutliers) {
        params.detect_outliers = true;
      }
      
      this.$message.info('正在执行数据清洗...');
      
      // 发送请求到后端
      this.$axios.post('http://10.76.213.64:5000/api/clean/missing', params)
        .then(response => {
          this.$message.success('数据清洗成功');
          console.log('清洗成功响应:', response);
          
          // 处理返回的数据
          if (response.data && response.data.data) {
            this.cleanedData = response.data.data.rows || [];
            // 如果返回了新的列信息，也可以更新
            if (response.data.data.columns) {
              this.tableColumns = response.data.data.columns;
            }
            
            // 更新数据集ID（如果后端返回了新的ID）
            if (response.data.data.dataset_id) {
              this.datasetId = response.data.data.dataset_id;
              console.log('数据清洗后更新数据集ID:', this.datasetId);
              this.$message.info(`更新数据集ID: ${this.datasetId}`);
            }
          }
        })
        .catch(error => {
          console.error('清洗失败详情:', error);
          let errorMessage = '数据清洗失败';
          if (error.response) {
            console.error('错误状态码:', error.response.status);
            console.error('错误响应数据:', error.response.data);
            errorMessage += `: 服务器返回错误代码 ${error.response.status}`;
          } else if (error.request) {
            console.error('请求未收到响应:', error.request);
            errorMessage += ': 服务器未响应请求';
          } else if (error.message) {
            errorMessage += `: ${error.message}`;
          }
 
          this.$message.error(errorMessage);
        });
        this.nextStep();
    },
    analyzeData() {
      // 检查是否有数据集ID
      if (!this.datasetId) {
        this.$message.error('缺少数据集ID，请先上传并清洗数据');
        return;
      }
      
      // 准备请求参数
      let params = {
        dataset_id: this.datasetId
      };
      
      // 根据选择的分析方法设置不同的参数
      if (this.analysisOptions.method === 'kmeans') {
        params.analysis_type = "kmeans";
        params.parameters = {
          n_clusters: this.analysisOptions.clusters || 3
        };
      } else if (this.analysisOptions.method === 'linear_regression') {
        params.analysis_type = "linear_regression";
        params.parameters = {
          test_size: 0.2 // 测试集比例，默认0.2
        };
      }
      
      this.$message.info('正在执行数据分析...');
      
      // 发送请求到后端
      this.$axios.post('http://10.76.213.64:5000/api/analysis/analyze', params)
        .then(response => {
          this.$message.success('数据分析成功');
          console.log('分析成功响应:', response);
          
          // 处理返回的数据
          if (response.data) {
            // 保存任务ID，用于后续可视化
            if (response.data.task_id) {
              this.analysisOptions.taskId = response.data.task_id;
              console.log('获取到分析任务ID:', this.analysisOptions.taskId);
            }
 
            // 分析完成后自动进入下一步（数据可视化）
            this.nextStep();
          }
        })
        .catch(error => {
          console.error('分析失败详情:', error);
          let errorMessage = '数据分析失败';
          if (error.response) {
            console.error('错误状态码:', error.response.status);
            console.error('错误响应数据:', error.response.data);
            errorMessage += `: 服务器返回错误代码 ${error.response.status}`;
          } else if (error.request) {
            console.error('请求未收到响应:', error.request);
            errorMessage += ': 服务器未响应请求';
          } else if (error.message) {
            errorMessage += `: ${error.message}`;
          }
          
          this.$message.error(errorMessage);
        });
    },
    generateChart() {
  // 检查是否有任务ID
  if (!this.analysisOptions.taskId) {
    this.$message.warning('请先执行数据分析以获取可视化所需的任务ID');
    return;
  }
  
  let apiUrl;
  let titles;
  let chartTypeMapping;
  
  // 根据分析方法选择不同的API端点和图表映射
  if (this.analysisOptions.method === 'kmeans') {
    apiUrl = `http://10.76.213.64:5000/api/viz/kmeans/${this.analysisOptions.taskId}`;
    
    // 定义图表类型与可视化类型的映射关系 (K-means)
    chartTypeMapping = {
      'scatter': 'scatter',  // 散点图对应聚类散点图
      'bar': 'silhouette',  // 柱状图对应轮廓系数图
      'heatmap': 'heatmap', // 热力图对应聚类中心热力图
      'radar': 'radar'      // 雷达图对应聚类特征雷达图
    };
    
    // 定义图表标题 (K-means)
    titles = {
      scatter: '聚类散点图',
      silhouette: '轮廓系数图',
      heatmap: '聚类中心热力图',
      radar: '聚类特征雷达图'
    };
  } else if (this.analysisOptions.method === 'linear_regression') {
    apiUrl = `http://10.76.213.64:5000/api/viz/linear_regression/${this.analysisOptions.taskId}`;
    
    // 定义图表类型与可视化类型的映射关系 (线性回归)
    chartTypeMapping = {
      'scatter': 'scatter',  // 散点图对应预测散点图
      'line': 'residual'    // 折线图对应残差图
    };
    
    // 定义图表标题 (线性回归)
    titles = {
      scatter: '预测散点图',
      residual: '残差图'
    };
  } else {
    this.$message.error('不支持的分析方法');
    return;
  }
  
  // 发送GET请求获取可视化数据
  this.$axios.get(apiUrl)
    .then(response => {
      if (response.data && response.data.status === 'success' && response.data.data && response.data.data.visualizations) {
        const visualizations = response.data.data.visualizations;
        
        // 清空现有图表容器
        const chartContainer = document.getElementById('chartContainer');
        chartContainer.innerHTML = '';
        
        // 获取用户选择的图表类型
        const selectedChartType = this.visualizationOptions.chartType;
        
        // 根据选择的图表类型显示对应的图表
        let visualizationType = chartTypeMapping[selectedChartType] || 'scatter';
        
        // 检查选择的可视化类型是否存在
        if (visualizations[visualizationType]) {
          const base64Data = visualizations[visualizationType];
          
          // 创建图片元素
          const img = document.createElement('img');
          img.src = `data:image/png;base64,${base64Data}`;
          img.alt = titles[visualizationType];
          img.style.width = '100%';
          img.style.height = 'auto';
          
          // 创建标题
          const titleElement = document.createElement('h3');
          titleElement.textContent = titles[visualizationType];
          titleElement.style.textAlign = 'center';
          titleElement.style.marginBottom = '20px';
          
          // 添加标题和图片到容器
          chartContainer.appendChild(titleElement);
          chartContainer.appendChild(img);
          
          this.$message.success(`${titles[visualizationType]}加载成功`);
        } else {
          this.$message.error(`所选图表类型 ${selectedChartType} 对应的可视化数据不存在`);
        }
      } else {
        throw new Error('获取可视化数据失败：响应格式不正确');
      }
    })
    .catch(error => {
      console.error('可视化失败详情:', error);
      this.$message.error(`可视化图表加载失败: ${error.message}`);
    });
},
    exportData() {
      // 检查是否有数据集ID
      if (!this.datasetId) {
        this.$message.error('缺少数据集ID，请先上传并清洗数据');
        return;
      }
      
      // 获取选择的导出格式
      const format = this.exportOptions.format;
      
      // 构建API URL，使用RESTful风格的路径
      const apiUrl = `http://10.76.213.64:5000/api/export/cleaned/${this.datasetId}`;
      
      // 准备请求参数
      const params = {
        format: format, // 'csv' 或 'excel'
        content: this.exportOptions.content // 选择的导出内容
      };
      
      this.$message.info('正在导出数据...');
      
      // 发送请求到后端
      this.$axios.get(apiUrl, {
        params: params,
        responseType: 'blob' // 设置响应类型为blob，用于文件下载
      })
        .then(response => {
          // 创建Blob对象
          const blob = new Blob([response.data]);
          
          // 获取文件类型
          let fileExtension = '';
          if (format === 'csv') {
            fileExtension = 'csv';
          } else if (format === 'excel') {
            fileExtension = 'xlsx';
          } else if (format === 'pdf') {
            fileExtension = 'pdf';
          }
          
          // 创建下载链接
          const link = document.createElement('a');
          link.href = URL.createObjectURL(blob);
          
          // 设置文件名
          const filename = `data_export_${new Date().getTime()}.${fileExtension}`;
          link.download = filename;
          
          // 触发下载
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          
          this.$message.success(`数据已成功导出为${format.toUpperCase()}格式`);
        })
        .catch(error => {
          console.error('导出失败详情:', error);
          let errorMessage = '数据导出失败';
          if (error.response) {
            console.error('错误状态码:', error.response.status);
            console.error('错误响应数据:', error.response.data);
            errorMessage += `: 服务器返回错误代码 ${error.response.status}`;
          } else if (error.request) {
            console.error('请求未收到响应:', error.request);
            errorMessage += ': 服务器未响应请求';
          } else if (error.message) {
            errorMessage += `: ${error.message}`;
          }
          
          this.$message.error(errorMessage);
        });
    },
    // 移动到下一步
    nextStep() {
      // 确保不超过最大步骤数
      if (this.currentStep < 4) {
        this.currentStep += 1;
        this.$message.success(`已进入步骤 ${this.currentStep + 1}`);
      }
    },
    
    // 移动到上一步
    prevStep() {
      if (this.currentStep > 0) {
        this.currentStep -= 1;
        this.$message.info(`已返回步骤 ${this.currentStep + 1}`);
      }
    },
    loadScript(src) {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
      });
    }
  },
  mounted() {
    // 动态加载 Vanta 所需的脚本
    this.loadScript("https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js")
      .then(() => this.loadScript("https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.dots.min.js"))
      .then(() => {
        this.vantaEffect = window.VANTA.DOTS({
          el: this.$refs.vantaRef,
          mouseControls: true,
          touchControls: true,
          gyroControls: false,
          minHeight: 200.00,
          minWidth: 200.00,
          scale: 1.00,
          scaleMobile: 1.00,
          color: 0x20000,
          color2: 0xfcfcfc,
          backgroundColor: 0xfafafa,
          size: 3.3,
          spacing: 40.0,
        });
      })
      .catch(err => {
        console.error("Vanta.js 加载失败：", err);
      });
  },
  beforeDestroy() {
    if (this.vantaEffect) this.vantaEffect.destroy();
  }
}
</script>

<style scoped>
.data-analysis {
  height: 100vh;  /* 设置为视口高度 */
  width: 100%;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;

}

.main-card {
  flex: 1;  /* 让卡片填满剩余空间 */
  display: flex;
  flex-direction: column;
  box-shadow: none;
  background-color: transparent;
  backdrop-filter: none;
  margin: 0;
  overflow: hidden;  /* 防止内容溢出 */

}

.step-content {
  flex: 1;  /* 让内容区域填满卡片剩余空间 */
  overflow-y: auto;  /* 添加垂直滚动条 */
  padding: 0 20px;
  margin-bottom: 60px;  /* 为底部按钮留出空间 */
}

/* 步骤控制按钮样式 */
.step-controls {
  position: fixed;  /* 固定在底部 */
  bottom: 20px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  padding: 15px;
  background-color: rgba(255, 255, 255, 0.9);
  z-index: 100;  /* 确保按钮在最上层 */
  box-shadow: none;
  background-color: transparent;
  backdrop-filter: none;
}

.step-controls .el-button {
  min-width: 100px;
  font-size: 16px;
}


.upload-preview-row {
  display: flex;
  flex-direction: row;
  gap: 32px;
  align-items: flex-start;
}
.upload-area-centered {
  flex: 1 1 320px;
  max-width: 600px;
}
.file-preview-area {
  flex: 2 1 0;
  min-width: 0;
  max-width: 100%;
  max-height: 400px; /* 你可以根据需要调整高度 */
  overflow: auto;
  background: #fff;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 12px;
  box-shadow: none;
  background-color: transparent;
  backdrop-filter: none;
}

/* 图表容器高度 */
#chartContainer {
  height: 60vh !important;
  min-height: 400px;
}
h3{

  font-size: 23px;
}

/* 自定义上传区域样式 */
.custom-upload-area {
  width: 100%;
  height: 180px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  transition: border-color .3s;
}

.custom-upload-area:hover {
  border-color: #409EFF;
}

.upload-icon {
  font-size: 28px;
  color: #8c939d;
  margin-bottom: 10px;
}

.upload-text {
  font-size: 14px;
  color: #606266;
  margin-bottom: 10px;
}

.upload-link {
  color: #409EFF;
  font-weight: 500;
  cursor: pointer;
}

.upload-tip {
  font-size: 12px;
  color: #909399;
}

/* 已选择文件样式 */
.selected-file {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
  padding: 8px 12px;
  background-color: #f5f7fa;
  border-radius: 4px;
  width: 100%;
}

.file-info {
  display: flex;
  align-items: center;
}

.file-name {
  margin: 0 8px;
  font-size: 14px;
  color: #606266;
}

.file-size {
  font-size: 12px;
  color: #909399;
}

.el-icon-delete {
  color: #F56C6C;
  cursor: pointer;
}

.el-icon-delete:hover {
  color: #f78989;
}
.upload-btn-center {
  display: flex;
  justify-content: center;
  margin-top: 10px;
  width: 100%;
}
.upload-form-vertical {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
}
.upload-form-vertical .el-input {
  width: 100%;
  margin-bottom: 16px;
}
.data-analysis {
  height: 100vh;
  width: 100%;
}
.export-card {
  box-shadow: none;
  background-color: transparent;
  backdrop-filter: none;
  border: none;
}
</style>

